<html>
<title>Writing and Using RISC-V exception handlers in RARS
</title>
<body>
<center>
<h3>Writing and Using RISC-V user mode exception handlers in RARS</h3>
</center>

<h3>Introduction</h3>

<i>Interrupts</i> are a way to break away from the current execution path and deal with a potentially time sensitive
issue and then return to the previous execution path. Interrupts fall into three categories: software, timer, and external.
Software interrupts are triggered by setting a bit in the interrupt pending CSR. Timer interrupts are triggered by a timer.
External interrupts come from outside the CPU. Both timer and external interrupts can be caused from tools from the tools menu.

<i>Synchronous traps</i> are caused by code not being able to continue on its current path without having additional actiion taken.
This can be because the code is incorrect (e.g. load access misaligned) or because action needs to be taken by the OS
(ecall, ebreak, page fault, etc).

Exception handlers allow programs to handle both of these cases. Every trap must be handled immediately either by the
program, or by RARS. System calls and breakpoints are normally handled by RARS, but other faults are generally handled
by printing an error message to the console. The program's exception handler doesn't have to print to console though.

Below is a simple handler which just skips over instructions generating traps:
<pre>
.text
main:
 	la t0,handler
 	csrrw zero, 5, t0 # set utvec (5) to the handlers address
 	csrrsi zero, 0, 1 # set interrupt enable bit in ustatus (0)
 	lw zero, 0        # trigger trap for Load access fault
 	j main


handler: # Just ignore it by moving epc (65) to the next instruction
	csrrw t0, 65, zero
	addi t0, t0, 4
	csrrw zero, 65, t0
	uret
</pre>

In order to have a working exception handler, the program must:
<ul>
    <li>Set utvec to the address of the handler code (the lowest two bits are special)</li>
    <li>Set the bits corresponding to the handled interrupts in uie</li>
    <li>Set the interrupt enable (lowest) bit in ustatus to enable the handler</li>
</ul>

And inside the handler, :
<ul>
    <li>The exception handler can return control to the program using
        the <i>uret</i> instruction.  This will place the uepc CSR value into the
        Program Counter, so be sure to increment it by 4 before returning if you want
        to skip over the instruction that caused the exception. It also resets some other
        state to before the exception, so jumping to the value in uepc instead is not recommended</li>
    <li> <i>ucause</i> contains the reason that the exception handler was called.
    </li>
    <li>Exception types declared in <tt>rars.SimulatorException</tt>, but
        not necessarily implemented, are INSTRUCTION_ADDR_MISALIGNED (0),
        INSTRUCTION_ACCESS_FAULT (1), ILLEGAL_INSTRUCTION(2),
        LOAD_ADDRESS_MISALIGNED(4), LOAD_ACCESS_FAULT(5),
        STORE_ADDRESS_MISALIGNED(6), STORE_ACCESS_FAULT(7), and ENVIRONMENT_CALL(8)
    </li>

    <li>When writing a non-trivial exception handler, your handler must first save
        general purpose register contents, then restore them before returning.</li>
</ul>

<p>The implementation of user-mode exception handlers in RARS is not complete and does not fully conform to the RISC-V
    privilidged specification, but it is based upon that and contributions to make it be more conformant would be appreciated.</p>

<p>For more details, refer to the RISC-V priviledged specification <b>https://riscv.org/specifications/privileged-isa/</b>;
    contributions to pull in more details into this page would be appreciated.</p>
</body>
</html>